void sip_register_task(void *pvParameters)
{
    while (1)
    {
        /* ================= CREATE SOCKET ================= */

        struct sockaddr_in server = {0};
        server.sin_family = AF_INET;
        server.sin_port = htons(SIP_PORT);
        server.sin_addr.s_addr = inet_addr(ASTERISK_IP);

        int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

        if (sock < 0) {
            ESP_LOGE(TAG, "Socket failed");
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        struct timeval timeout = {
            .tv_sec = 3,
            .tv_usec = 0
        };

        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
                   &timeout, sizeof(timeout));

        /* ================= FIRST REGISTER ================= */

        char register_msg[512];

        snprintf(register_msg, sizeof(register_msg),
            "REGISTER sip:%s SIP/2.0\r\n"
            "Via: SIP/2.0/UDP 0.0.0.0:5062\r\n"
            "From: <sip:1001@%s>;tag=1234\r\n"
            "To: <sip:1001@%s>\r\n"
            "Call-ID: esp32-0001\r\n"
            "CSeq: 1 REGISTER\r\n"
            "Contact: <sip:1001@0.0.0.0:5062>\r\n"
            "Expires: 300\r\n"
            "Content-Length: 0\r\n"
            "\r\n",
            ASTERISK_IP,
            ASTERISK_IP,
            ASTERISK_IP);

        ESP_LOGI(TAG, "Sending REGISTER...");

        sendto(sock,
               register_msg,
               strlen(register_msg),
               0,
               (struct sockaddr *)&server,
               sizeof(server));

        /* ================= RECEIVE 401 ================= */

        char response[1024];
        socklen_t addr_len = sizeof(server);

        int len = recvfrom(sock,
                           response,
                           sizeof(response) - 1,
                           0,
                           (struct sockaddr *)&server,
                           &addr_len);

        if (len <= 0) {
            ESP_LOGE(TAG, "No response");
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        response[len] = '\0';

        printf("401 RESPONSE:\n%s\n", response);

        if (!strstr(response, "401")) {
            ESP_LOGE(TAG, "Expected 401 Unauthorized");
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        /* ================= EXTRACT NONCE ================= */

        char sip_nonce[256] = {0};

        char *n = strstr(response, "nonce=\"");

        if (!n) {
            ESP_LOGE(TAG, "No nonce found");
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        n += 7;

        char *end = strchr(n, '"');

        if (!end) {
            ESP_LOGE(TAG, "Bad nonce format");
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        size_t nlen = end - n;

        if (nlen >= sizeof(sip_nonce)) {
            ESP_LOGE(TAG, "Nonce too long");
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        strncpy(sip_nonce, n, nlen);
        sip_nonce[nlen] = '\0';

        ESP_LOGI(TAG, "Nonce: %s", sip_nonce);

        /* ================= EXTRACT REALM ================= */

        char sip_realm[128] = {0};

        char *r = strstr(response, "realm=\"");

        if (!r) {
            ESP_LOGE(TAG, "Realm not found");
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        r += 7;

        char *rend = strchr(r, '"');

        if (!rend) {
            ESP_LOGE(TAG, "Bad realm format");
            close(sock);
            vTaskDelay(pdMS_TO_TICKS(5000));
            continue;
        }

        size_t rlen = rend - r;

        strncpy(sip_realm, r, rlen);
        sip_realm[rlen] = '\0';

        ESP_LOGI(TAG, "Realm: %s", sip_realm);

        /* ================= COMPUTE DIGEST ================= */

        char response_hash[64];

        sip_compute_response(
            "1001",
            sip_realm,
            "secret123",
            sip_nonce,
            "sip:" ASTERISK_IP,
            response_hash);

        /* ================= AUTH REGISTER ================= */

        char auth[1024];

        snprintf(auth, sizeof(auth),
            "REGISTER sip:%s SIP/2.0\r\n"
            "Via: SIP/2.0/UDP 0.0.0.0:5062\r\n"
            "From: <sip:1001@%s>;tag=1234\r\n"
            "To: <sip:1001@%s>\r\n"
            "Call-ID: esp32-0001\r\n"
            "CSeq: 2 REGISTER\r\n"
            "Contact: <sip:1001@0.0.0.0:5062>\r\n"
            "Authorization: Digest username=\"1001\", realm=\"%s\", nonce=\"%s\", uri=\"sip:%s\", response=\"%s\"\r\n"
            "Expires: 300\r\n"
            "Content-Length: 0\r\n"
            "\r\n",
            ASTERISK_IP,
            ASTERISK_IP,
            ASTERISK_IP,
            sip_realm,
            sip_nonce,
            ASTERISK_IP,
            response_hash);

        ESP_LOGI(TAG, "Sending AUTH REGISTER...");

        sendto(sock,
               auth,
               strlen(auth),
               0,
               (struct sockaddr *)&server,
               sizeof(server));

        /* ================= FINAL RESPONSE ================= */

        char final_resp[1024];

        int len2 = recvfrom(sock,
                            final_resp,
                            sizeof(final_resp) - 1,
                            0,
                            (struct sockaddr *)&server,
                            &addr_len);

        if (len2 > 0) {
            final_resp[len2] = '\0';

            printf("FINAL RESPONSE:\n%s\n", final_resp);

            if (strstr(final_resp, "200 OK")) {
                ESP_LOGI(TAG, "🎉 SIP REGISTER SUCCESS");
            } else {
                ESP_LOGW(TAG, "REGISTER FAILED");
            }
        } else {
            ESP_LOGW(TAG, "No final response");
        }

        close(sock);

        ESP_LOGI(TAG, "Waiting 240 seconds before refreshing registration...");

        vTaskDelay(pdMS_TO_TICKS(240000));
    }
}